#include "../Arduino_DataBus.h"

#if defined(ESP32) && (CONFIG_IDF_TARGET_ESP32S3)

#ifndef _ARDUINO_GC9503V_RGBPANEL_H_
#define _ARDUINO_GC9503V_RGBPANEL_H_

#include "../Arduino_GFX.h"
#include "../databus/Arduino_ESP32RGBPanel.h"

#define ST7701_TFTWIDTH 480
#define ST7701_TFTHEIGHT 864

static const uint8_t gc9503v_type1_init_operations[] = {
    BEGIN_WRITE,
    WRITE_COMMAND_8, 0xF0,
    WRITE_BYTES, 5, 0x55, 0xAA, 0x52, 0x08, 0x00,

    WRITE_C8_D16, 0xF6, 0x5A, 0x87,

    WRITE_C8_D8, 0xC1, 0x3F,
    WRITE_C8_D8, 0xC2, 0x0E,
    WRITE_C8_D8, 0xC6, 0xF8,
    WRITE_C8_D8, 0xC9, 0x10,
    WRITE_C8_D8, 0xCD, 0x25,
    WRITE_C8_D8, 0xF8, 0x8A,
    WRITE_C8_D8, 0xAC, 0x45,
    WRITE_C8_D8, 0xA0, 0xDD,
    WRITE_C8_D8, 0xA7, 0x47,

    WRITE_COMMAND_8, 0xFA,
    WRITE_BYTES, 4, 0x00, 0x00, 0x00, 0x04,

    WRITE_C8_D8, 0xA3, 0xEE,

    WRITE_COMMAND_8, 0xFD,
    WRITE_BYTES, 3, 0x28, 0x28, 0x00,

    WRITE_C8_D8, 0x71, 0x48,
    WRITE_C8_D8, 0x72, 0x48,
    WRITE_C8_D16, 0x73, 0x00, 0x44,
    WRITE_C8_D8, 0x97, 0xEE,
    WRITE_C8_D8, 0x83, 0x93,
    WRITE_C8_D8, 0x9A, 0x72,
    WRITE_C8_D8, 0x9B, 0x5a,
    WRITE_C8_D16, 0x82, 0x2c, 0x2c,
    WRITE_C8_D8, 0xB1, 0x10,

    WRITE_COMMAND_8, 0x6D,
    WRITE_BYTES, 32,
    0x00, 0x1F, 0x19, 0x1A,
    0x10, 0x0e, 0x0c, 0x0a,
    0x02, 0x07, 0x1E, 0x1E,
    0x1E, 0x1E, 0x1E, 0x1E,
    0x1E, 0x1E, 0x1E, 0x1E,
    0x1E, 0x1E, 0x08, 0x01,
    0x09, 0x0b, 0x0D, 0x0F,
    0x1a, 0x19, 0x1f, 0x00,

    WRITE_COMMAND_8, 0x64,
    WRITE_BYTES, 16,
    0x38, 0x05, 0x01, 0xdb,
    0x03, 0x03, 0x38, 0x04,
    0x01, 0xdc, 0x03, 0x03,
    0x7A, 0x7A, 0x7A, 0x7A,

    WRITE_COMMAND_8, 0x65,
    WRITE_BYTES, 16,
    0x38, 0x03, 0x01, 0xdd,
    0x03, 0x03, 0x38, 0x02,
    0x01, 0xde, 0x03, 0x03,
    0x7A, 0x7A, 0x7A, 0x7A,

    WRITE_COMMAND_8, 0x66,
    WRITE_BYTES, 16,
    0x38, 0x01, 0x01, 0xdf,
    0x03, 0x03, 0x38, 0x00,
    0x01, 0xe0, 0x03, 0x03,
    0x7A, 0x7A, 0x7A, 0x7A,

    WRITE_COMMAND_8, 0x67,
    WRITE_BYTES, 16,
    0x30, 0x01, 0x01, 0xe1,
    0x03, 0x03, 0x30, 0x02,
    0x01, 0xe2, 0x03, 0x03,
    0x7A, 0x7A, 0x7A, 0x7A,

    WRITE_COMMAND_8, 0x68,
    WRITE_BYTES, 13,
    0x00, 0x08, 0x15, 0x08,
    0x15, 0x7A, 0x7A, 0x08,
    0x15, 0x08, 0x15, 0x7A,
    0x7A,

    WRITE_COMMAND_8, 0x60,
    WRITE_BYTES, 8,
    0x38, 0x08, 0x7A, 0x7A,
    0x38, 0x09, 0x7A, 0x7A,

    WRITE_COMMAND_8, 0x63,
    WRITE_BYTES, 8,
    0x31, 0xe4, 0x7A, 0x7A,
    0x31, 0xe5, 0x7A, 0x7A,

    WRITE_C8_D8, 0x6B, 0x07,

    WRITE_C8_D16, 0x7A, 0x08, 0x13,

    WRITE_C8_D16, 0x7B, 0x08, 0x13,

    WRITE_COMMAND_8, 0xD1,
    WRITE_BYTES, 52,
    0x00, 0x00, 0x00, 0x04,
    0x00, 0x12, 0x00, 0x18,
    0x00, 0x21, 0x00, 0x2a,
    0x00, 0x35, 0x00, 0x47,
    0x00, 0x56, 0x00, 0x90,
    0x00, 0xe5, 0x01, 0x68,
    0x01, 0xd5, 0x01, 0xd7,
    0x02, 0x36, 0x02, 0xa6,
    0x02, 0xee, 0x03, 0x48,
    0x03, 0xa0, 0x03, 0xba,
    0x03, 0xc5, 0x03, 0xd0,
    0x03, 0xE0, 0x03, 0xea,
    0x03, 0xFa, 0x03, 0xFF,

    WRITE_COMMAND_8, 0xD2,
    WRITE_BYTES, 52,
    0x00, 0x00, 0x00, 0x04,
    0x00, 0x12, 0x00, 0x18,
    0x00, 0x21, 0x00, 0x2a,
    0x00, 0x35, 0x00, 0x47,
    0x00, 0x56, 0x00, 0x90,
    0x00, 0xe5, 0x01, 0x68,
    0x01, 0xd5, 0x01, 0xd7,
    0x02, 0x36, 0x02, 0xa6,
    0x02, 0xee, 0x03, 0x48,
    0x03, 0xa0, 0x03, 0xba,
    0x03, 0xc5, 0x03, 0xd0,
    0x03, 0xE0, 0x03, 0xea,
    0x03, 0xFa, 0x03, 0xFF,

    WRITE_COMMAND_8, 0xD3,
    WRITE_BYTES, 52,
    0x00, 0x00, 0x00, 0x04,
    0x00, 0x12, 0x00, 0x18,
    0x00, 0x21, 0x00, 0x2a,
    0x00, 0x35, 0x00, 0x47,
    0x00, 0x56, 0x00, 0x90,
    0x00, 0xe5, 0x01, 0x68,
    0x01, 0xd5, 0x01, 0xd7,
    0x02, 0x36, 0x02, 0xa6,
    0x02, 0xee, 0x03, 0x48,
    0x03, 0xa0, 0x03, 0xba,
    0x03, 0xc5, 0x03, 0xd0,
    0x03, 0xE0, 0x03, 0xea,
    0x03, 0xFa, 0x03, 0xFF,

    WRITE_COMMAND_8, 0xD4,
    WRITE_BYTES, 52,
    0x00, 0x00, 0x00, 0x04,
    0x00, 0x12, 0x00, 0x18,
    0x00, 0x21, 0x00, 0x2a,
    0x00, 0x35, 0x00, 0x47,
    0x00, 0x56, 0x00, 0x90,
    0x00, 0xe5, 0x01, 0x68,
    0x01, 0xd5, 0x01, 0xd7,
    0x02, 0x36, 0x02, 0xa6,
    0x02, 0xee, 0x03, 0x48,
    0x03, 0xa0, 0x03, 0xba,
    0x03, 0xc5, 0x03, 0xd0,
    0x03, 0xE0, 0x03, 0xea,
    0x03, 0xFa, 0x03, 0xFF,

    WRITE_COMMAND_8, 0xD5,
    WRITE_BYTES, 52,
    0x00, 0x00, 0x00, 0x04,
    0x00, 0x12, 0x00, 0x18,
    0x00, 0x21, 0x00, 0x2a,
    0x00, 0x35, 0x00, 0x47,
    0x00, 0x56, 0x00, 0x90,
    0x00, 0xe5, 0x01, 0x68,
    0x01, 0xd5, 0x01, 0xd7,
    0x02, 0x36, 0x02, 0xa6,
    0x02, 0xee, 0x03, 0x48,
    0x03, 0xa0, 0x03, 0xba,
    0x03, 0xc5, 0x03, 0xd0,
    0x03, 0xE0, 0x03, 0xea,
    0x03, 0xFa, 0x03, 0xFF,

    WRITE_COMMAND_8, 0xD6,
    WRITE_BYTES, 52,
    0x00, 0x00, 0x00, 0x04,
    0x00, 0x12, 0x00, 0x18,
    0x00, 0x21, 0x00, 0x2a,
    0x00, 0x35, 0x00, 0x47,
    0x00, 0x56, 0x00, 0x90,
    0x00, 0xe5, 0x01, 0x68,
    0x01, 0xd5, 0x01, 0xd7,
    0x02, 0x36, 0x02, 0xa6,
    0x02, 0xee, 0x03, 0x48,
    0x03, 0xa0, 0x03, 0xba,
    0x03, 0xc5, 0x03, 0xd0,
    0x03, 0xE0, 0x03, 0xea,
    0x03, 0xFa, 0x03, 0xFF,

    WRITE_C8_D8, 0x3a, 0x66,

    WRITE_COMMAND_8, 0x11,
    END_WRITE,

    DELAY, 200,

    BEGIN_WRITE,
    WRITE_COMMAND_8, 0x29,
    END_WRITE};

class Arduino_GC9503V_RGBPanel : public Arduino_GFX
{
public:
  Arduino_GC9503V_RGBPanel(
      Arduino_ESP32RGBPanel *bus, int8_t rst = GFX_NOT_DEFINED, int16_t w = ST7701_TFTWIDTH, int16_t h = ST7701_TFTHEIGHT,
      const uint8_t *init_operations = gc9503v_type1_init_operations,
      size_t init_operations_len = sizeof(gc9503v_type1_init_operations));

  void begin(int32_t speed = GFX_NOT_DEFINED) override;
  void writePixelPreclipped(int16_t x, int16_t y, uint16_t color) override;
  void writeFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color) override;
  void writeFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color) override;
  void writeFillRectPreclipped(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color) override;
  void draw16bitRGBBitmap(int16_t x, int16_t y, uint16_t *bitmap, int16_t w, int16_t h) override;
  void draw16bitBeRGBBitmap(int16_t x, int16_t y, uint16_t *bitmap, int16_t w, int16_t h) override;

  uint16_t *getFramebuffer();

protected:
  uint16_t *_framebuffer;
  Arduino_ESP32RGBPanel *_bus;
  int8_t _rst;
  const uint8_t *_init_operations;
  size_t _init_operations_len;

private:
};

#endif // _ARDUINO_GC9503V_RGBPANEL_H_

#endif // #if defined(ESP32) && (CONFIG_IDF_TARGET_ESP32S3)
